#include "planner/operator.h"

#include "common/hash_util.h"
#include "common/node_utils.h"
#include "planner/operator_visitor.h"
extern "C" {
#include <nodes/nodes.h>
}

namespace optimizer {

std::shared_ptr<Operator> Operator::Copy() const {
  auto copy = std::make_shared<Operator>(type_, copyObject(expressions_));
  copy->SetFilter(copyObject(project_));
  copy->SetFilter(copyObject(filter_));

  return copy;
}
std::shared_ptr<Operator> Operator::CopyWithChildren() const {
  auto copy = Operator::Copy();
  for (const auto& child : children_) {
    copy->AddChild(child->CopyWithChildren());
  }

  return copy;
}

hash_t Operator::Hash() const {
  auto hash = HashUtil::CombineHashes(HashUtil::Hash(type_), NodeUtils::ExprHash(expressions_));
  hash = HashUtil::CombineHashes(hash, NodeUtils::ExprHash(project_));
  hash = HashUtil::CombineHashes(hash, NodeUtils::ExprHash(filter_));
  return hash;
}
hash_t Operator::HashWithChildren() const {
  auto hash = Operator::Hash();
  for (const auto& child : children_) {
    hash = HashUtil::CombineHashes(hash, child->HashWithChildren());
  }
  return hash;
}

bool Operator::operator==(const Operator& r) const {
  return GetOpType() == r.GetOpType() && equal(expressions_, r.expressions_) && equal(project_, r.project_) &&
         equal(filter_, r.filter_);
}

void Operator::Accept(OperatorVisitor* v) {
  v->Visit(this);
}

}  // namespace optimizer